#include<iostream>
#include<cstring>
#include<string>
#include <poll.h>
#include "Log.hpp"
#include "Socket.hpp"
#include<unistd.h>

#define NUM 100
#define TIMEOUT 1000
#define FD_NONE -1

class PollServer
{
private:
    int _listen_sock; 
    uint16_t _port; 
    pollfd* _fds;
    int _nfds;
    int _timeout;
public:
    PollServer(uint16_t port = 8081,int nfds = NUM,int timeout = TIMEOUT) : _port(port),_nfds(nfds),_timeout(timeout)
    {
        _listen_sock = Socket::GetSocket(); 
        Socket::Bind(_listen_sock,_port); 
        Socket::Listen(_listen_sock);

        _fds = new struct pollfd[_nfds]; 
        //初始化所有文件描述符
        for(int i = 0 ; i < _nfds ; i++)
            _fds[i].fd = FD_NONE; 
        
        //监听套接字放在第一个
        _fds[0].fd = _listen_sock;
        _fds[0].events = POLLIN;
    }
    ~PollServer()
    {
        if(_listen_sock >= 0)
            close(_listen_sock);
        delete [] _fds;
    }


    void Start()
    {
        while(true)
        {
            DebugPrint();
            int n = poll(_fds,_nfds,_timeout);
            switch(n)
            {
                case 0: DLOG("tmieout.....\n"); break;
                case -1: DLOG("poll error , %d : %s\n",errno,strerror(errno)); break; 
                default: EventHandler();break;

            }
        }
    }

private:
    void EventHandler()
    {
        //遍历一遍数组
        for(int i = 0 ; i  < _nfds ; i++)
        {
            if(_fds[i].fd == FD_NONE) continue; 
            if(_fds[i].revents & POLLIN) //如果有输入事件
            {
                if(_fds[i].fd == _listen_sock) Accepter();
                else Recver(i);
            }
        }
    }

    void Accepter()
    {
        std::string client_ip;
        uint16_t client_port;
        int sock = Socket::Accept(_listen_sock,&client_ip,&client_port); 
        if(sock < 0 )
        {
            DLOG("socket accept fail\n"); 
            return ;
        }
        //找一个空位置
        int pos = 1;
        for(; pos < _nfds ; pos++)
        {
            if(_fds[pos].fd == FD_NONE) break;
        }
        if(pos == _nfds)
        {
            DLOG("fds already\n"); 
            close(sock);
        }else
        {
            _fds[pos].fd = sock;
            _fds[pos].events = POLLIN;
        }
    }

    void Recver(int pos)
    {
        char buff[1024] = {0};
        int n = recv(_fds[pos].fd,buff,sizeof(buff) - 1 , 0);
        if(n > 0)
        {
            buff[n] = 0 ;
            DLOG("client [%d]# %s\n",_fds[pos].fd , buff);
        }else if(n == 0)
        {
            DLOG("client[%d] quit, me too...\n",_fds[pos].fd);
            close(_fds[pos].fd);
            _fds[pos].fd = FD_NONE;
        }else
        {
            DLOG("client[%d] recv error, %d : %s\n",_fds[pos].fd,errno,strerror(errno));
            close(_fds[pos].fd);
            _fds[pos].fd = FD_NONE;
        }
    }

    void DebugPrint()
    {
        std::cout << "_fd_array[]: ";
        for(int i = 0; i < _nfds; i++)
        {
            if(_fds[i].fd == FD_NONE) continue;
            std::cout << _fds[i].fd << " ";
        }
        std::cout << std::endl;
    }
};